Skip to content

Conversation

@blyoa
Copy link
Contributor

@blyoa blyoa commented Oct 3, 2025

This Pull Request adds a priority property to the Decoration interface, allowing users to control the display order of multiple decorations.

The default priority is set to zero to align with the priority property of prop_type_add.

prop_type_add({name}, {props})		*prop_type_add()* *E969* *E970*
		Add a text property type {name}.  If a property type with this
		name already exists an error is given.  Nothing is returned.
		{props} is a dictionary with these optional fields:
		   bufnr	define the property only for this buffer; this
				avoids name collisions and automatically
				clears the property types when the buffer is
				deleted.
		   highlight	name of highlight group to use
		   priority	when a character has multiple text
				properties the one with the highest priority
				will be used; negative values can be used, the
				default priority is zero

https://github.com/vim/vim/blob/fdeb721251481c26c230a0cd793cb89c2534c206/runtime/doc/textprop.txt#L426-L438

Summary by CodeRabbit

  • New Features

    • Added optional priority on decorations to control visual stacking order; higher priority renders above lower.
    • Priority is propagated to Vim/Neovim so rendering and listing reflect priority consistently.
    • Decoration listings now include priority; unspecified values default to 0.
    • Backwards compatible: existing usages continue to work without specifying priority.
  • Tests

    • Added and updated tests covering multiple priorities, defaulting behavior, and listing assertions.

@coderabbitai
Copy link

coderabbitai bot commented Oct 3, 2025

Walkthrough

Adds an optional per-decoration priority (default 0) to Decoration objects and propagates priority through prop-type creation, decoration rendering (Vim/Neovim APIs), and listing; tests updated to cover multiple priorities and defaulting.

Changes

Cohort / File(s) Summary of Changes
Decoration priority plumbing
buffer/decoration.ts
Adds optional priority?: number to Decoration; introduces DEFAULT_DECORATION_PRIORITY; groups/keys prop types by (prefix, priority, highlight); creates prop types on demand including priority in type identifiers/options; passes priority to prop_add/extmark creation; listDecorations retrieves and returns priority; undecorate flow continues to operate with expanded metadata.
Tests updated for priority
buffer/decoration_test.ts
Updates expectations to include priority in type identifiers (e.g., ...:0:Title), adds scenario testing multiple decorations with different priorities, and asserts priority propagation and defaulting to 0 in list results and decoration objects.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Caller
  participant Buffer as buffer/decoration
  participant Backend as Vim/Neovim API

  Caller->>Buffer: decorate([{ highlight, priority?, ... }])
  Note over Buffer: derive prop-type key = (prefix, priority, highlight)
  alt prop-type missing
    Buffer->>Backend: prop_type_add / prop_type_create (include priority)
  end
  Buffer->>Backend: prop_add_list / nvim_buf_set_extmark (attach decorations with priority)
  Caller->>Buffer: listDecorations()
  Backend-->>Buffer: prop_type_get / extmark info (includes priority)
  Buffer-->>Caller: Decoration[] (each includes priority, default 0)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

I hopped through highlights, small and spry,
Numbers tucked beneath each dye.
A nibble here, a carrot-priority true,
Layers sorted, tidy view.
I stamp my paw — extmarks align, hooray! 🥕

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Title Check ⚠️ Warning The title accurately describes the main change of adding a priority property to the Decoration interface but includes an extraneous emoji that adds noise and does not aid clarity. Remove the emoji and use a concise title such as “Add a priority property to Decoration” to clearly convey the change without extra noise.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2f703e0 and 664a39b.

📒 Files selected for processing (2)
  • buffer/decoration.ts (7 hunks)
  • buffer/decoration_test.ts (7 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • buffer/decoration.ts
  • buffer/decoration_test.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: test (ubuntu-latest, ~2.3, v9.1.1646, v0.11.3)
  • GitHub Check: test (macos-latest, 2.x, v9.1.1646, v0.11.3)
  • GitHub Check: test (windows-latest, 2.x, v9.1.1646, v0.11.3)
  • GitHub Check: test (ubuntu-latest, 2.x, v9.1.1646, v0.11.3)
  • GitHub Check: test (macos-latest, ~2.3, v9.1.1646, v0.11.3)
  • GitHub Check: test (windows-latest, ~2.3, v9.1.1646, v0.11.3)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
buffer/decoration.ts (2)

38-43: Clarify JSDoc: negative values allowed

Call out that negative priorities are allowed (per Vim’s behavior) to set expectations for consumers.

Apply this diff to the JSDoc:

-  /**
-   * Priority for the decoration (higher numbers are displayed on top)
-   * Defaults to 0 if not specified
-   */
+  /**
+   * Priority for the decoration (higher numbers are displayed on top).
+   * Negative values are allowed. Defaults to 0 when omitted.
+   */

260-276: Make Vim listing faster and more robust (fallback + cache + safe highlight parse)

  • Avoid 1 RPC per prop by caching type->priority.
  • Fallback to 0 when prop_type_get() returns no priority.
  • Parse highlight without relying on .split(':').pop() so it won’t break if a highlight ever contains a colon.

Apply this diff:

-  return Promise.all(
-    props
-      .filter((prop) => prop.type.startsWith(`${prefix}:`))
-      .map(async (prop) => {
-        const propType = await vimFn.prop_type_get(denops, prop.type) as {
-          priority: number;
-        };
-        return ({
-          line: prop.lnum,
-          column: prop.col,
-          length: prop.length,
-          highlight: prop.type.split(":").pop() as string,
-          priority: propType.priority,
-        });
-      }),
-  );
+  const filtered = props.filter((prop) => prop.type.startsWith(`${prefix}:`));
+  const typePriorityCache = new Map<string, number>();
+  return Promise.all(filtered.map(async (prop) => {
+    let prio = typePriorityCache.get(prop.type);
+    if (prio == null) {
+      const t = await vimFn.prop_type_get(denops, prop.type) as { priority?: number };
+      prio = t.priority ?? DEFAULT_DECORATION_PRIORITY;
+      typePriorityCache.set(prop.type, prio);
+    }
+    const head = `${prefix}:${prio}:`;
+    const highlight = prop.type.startsWith(head)
+      ? prop.type.slice(head.length)
+      : prop.type; // safe fallback
+    return {
+      line: prop.lnum,
+      column: prop.col,
+      length: prop.length,
+      highlight,
+      priority: prio,
+    };
+  }));
buffer/decoration_test.ts (1)

57-66: Avoid asserting internal Vim prop type naming

Asserting the exact type string (including embedded priority) tightly couples tests to an internal naming scheme. Prefer verifying behavior via listDecorations or by checking the priority through prop_type_get() for the relevant type(s).

Example alternatives:

  • Use listDecorations to assert highlight range and omit type internals.
  • Or, derive the prop type name, call prop_type_get(), and assert priority: 0.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9d814ea and 2f703e0.

📒 Files selected for processing (2)
  • buffer/decoration.ts (7 hunks)
  • buffer/decoration_test.ts (7 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
buffer/decoration_test.ts (2)
function/buffer.ts (1)
  • bufnr (301-307)
buffer/decoration.ts (2)
  • decorate (78-92)
  • listDecorations (153-166)
buffer/decoration.ts (1)
batch/batch.ts (2)
  • batch (67-73)
  • batch (187-203)
🔇 Additional comments (8)
buffer/decoration.ts (5)

12-12: Good default constant

DEFAULT_DECORATION_PRIORITY = 0 aligns with Vim’s default behavior.


63-63: Nice example

Including an explicit priority in the example helps demonstrate ordering semantics.


175-208: Vim prop types keyed by (priority, highlight): LGTM

Type naming and caching strategy make priority part of the prop-type identity; batch creation looks correct.


352-353: Default priority fallback (Neovim) looks good

Safe defaulting to 0 when the detail is missing.


298-299: Extmark priority supported since Neovim v0.7/API level 7
The priority option on nvim_buf_set_extmark is available since API level 7 (Neovim ≥ 0.7), so no change is needed if your minimum supported version is v0.7 or newer.

buffer/decoration_test.ts (3)

126-172: Priority coexistence test: LGTM

Validates multiple decorations of the same highlight with different priorities across hosts.


185-215: listDecorations priority defaults and propagation: LGTM

Covers default priority (0) and explicit priority (10).


230-247: Undecorate tests with priorities: LGTM

Both full-buffer and ranged clears behave correctly with prioritized decorations.

Also applies to: 262-287

@lambdalisue
Copy link
Member

I'm sorry but we first need to fix CI (it's our fault.)

@lambdalisue
Copy link
Member

@blyoa Could you rebase from the latest main and force push? CI would be fixed (prob. CI fails to generate coverage report on Windows but we will ignore that.)

@blyoa blyoa force-pushed the add-priority-property-to-decoration branch from 2f703e0 to 664a39b Compare October 5, 2025 23:57
@codecov
Copy link

codecov bot commented Oct 5, 2025

Codecov Report

❌ Patch coverage is 97.43590% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 84.82%. Comparing base (cfdf259) to head (664a39b).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
buffer/decoration.ts 97.43% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #295      +/-   ##
==========================================
+ Coverage   84.77%   84.82%   +0.04%     
==========================================
  Files          64       64              
  Lines        2864     2879      +15     
  Branches      277      281       +4     
==========================================
+ Hits         2428     2442      +14     
- Misses        434      435       +1     
  Partials        2        2              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@blyoa
Copy link
Contributor Author

blyoa commented Oct 6, 2025

@lambdalisue
I have rebased onto the latest main branch and force pushed the head branch.
(As you mentioned, coverage generation on Windows failed)

@lambdalisue lambdalisue merged commit 39c1554 into vim-denops:main Oct 6, 2025
9 of 10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants